package com.rockcent.mall.controller;

import com.rockcent.common.common.JsonResult;
import com.rockcent.common.common.PageResult;
import com.rockcent.common.common.RestDoing;
import com.rockcent.common.controller.BaseController;
import com.rockcent.common.utils.ExcelExportUtils;
import com.rockcent.common.utils.RBeanUtils;
import com.rockcent.mall.Routes;
import com.rockcent.mall.helper.UserHelper;
import com.rockcent.mall.lib.domain.Merchant;
import com.rockcent.mall.lib.domain.MerchantFund;
import com.rockcent.mall.lib.domain.MerchantFundFlow;
import com.rockcent.mall.lib.domain.enumclass.FundTransactionFlow;
import com.rockcent.mall.lib.domain.enumclass.MerchantFundFlowTransactionType;
import com.rockcent.mall.lib.domain.enumclass.MerchantPayType;
import com.rockcent.mall.lib.dto.MerchantFundDto;
import com.rockcent.mall.lib.dto.MerchantFundFlowDto;
import com.rockcent.mall.lib.dto.UserInfoDto;
import com.rockcent.mall.lib.helper.BaseUserHelper;
import com.rockcent.mall.lib.repository.MerchantFundFlowRepository;
import com.rockcent.mall.lib.repository.MerchantFundRepository;
import com.rockcent.mall.lib.repository.MerchantRepository;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by DK on 16/11/19.
 * 平台商家资金流水模块
 */
@RestController
public class MallMerchantFundFlowController extends BaseController {
    private static final Logger log = LoggerFactory.getLogger(MallMerchantFundFlowController.class);

    @Autowired
    private UserHelper userHelper;

    @Autowired
    private MerchantFundRepository merchantFundRepository;

    @Autowired
    private MerchantFundFlowRepository merchantFundFlowRepository;

    @Autowired
    private MerchantRepository merchantRepository;

    /**
     * @api {get} /mall/merchant/fund/flow/page 平台 财务 商家资金 分页
     * @apiGroup MALL_MERCHANT_FUND
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {String} merchantName 商家名称
     * @apiParam {String} merchantAccount 商家帐号
     *
     * @apiSuccess {String} merchantName 商家名称
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {BigDecimal} totalAmount 账户总金额
     * @apiSuccess {BigDecimal} totalIncome 账户累计收入
     * @apiSuccess {BigDecimal} totalExpend 账户累计支出
     * @apiSuccess {BigDecimal} availableAmount 可用余额
     * @apiSuccess {BigDecimal} frozen 锁定余额
     * @apiSuccess {Long} merchantId 商家ID
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     * "code": "1",
     * "desc": "成功"
     * "data":{
     *      "totalAmount": 3242,
     *      "operationAmount": 3242,
     *      "totalIncome": 3242,
     *      "totalExpend": 3242,
     *      "availableAmount": 3242,
     *      "frozen": 3242,
     *      "merchantName": "张三",
     *      "merchantId": 1,
     *      "mallId": 1
     *  }
     * }
     */
    @RequestMapping(value = Routes.MALL_MERCHANT_FUND_FLOW_PAGE, method = RequestMethod.GET)
    private JsonResult mallMerchantFundFlowPage(HttpServletRequest request, MerchantFundDto dto){
        log.info("======================>userHelper:{},{}",merchantFundRepository,userHelper);
        UserInfoDto userDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            PageResult<MerchantFundDto> pageResult = merchantFundRepository.findMallMerchantFundFlowPage(userDto.mall.getId(), dto.getMerchantName(), dto.getMerchantAccount(), this.getPage(dto.getPageNo(), dto.getPageSize()));
            pageResult.data.stream().map(merchantFund ->{
                //TODO 累计收入   充值算收入?
                List<MerchantFundFlow> merchantFundFlowList = merchantFundFlowRepository.findByMerchantIdAndMallId(merchantFund.getMerchantId(), merchantFund.getMallId());
                BigDecimal expend = BigDecimal.ZERO;
                BigDecimal totalExpend = BigDecimal.ZERO;
                BigDecimal income = BigDecimal.ZERO;
                for (MerchantFundFlow merchantFundFlow : merchantFundFlowList) {

                    if (FundTransactionFlow.EXPEND == merchantFundFlow.getTransactionFlow()) { //若有提现,到时要提现 增值服务之类,要加条件判断
                        if (MerchantFundFlowTransactionType.A_APPLY_WITHDRAW_EXPEND == merchantFundFlow.getTransactionType()) {
                            totalExpend = totalExpend.add(merchantFundFlow.getOperationAmount());
                        }else{
                            expend = expend.add(merchantFundFlow.getOperationAmount());
                        }
                    }
                    if (FundTransactionFlow.INCOME == merchantFundFlow.getTransactionFlow()) { //若有充值,要加条件判断
                        income = income.add(merchantFundFlow.getOperationAmount());
                    }
                }


                merchantFund.setTotalIncome(Double.valueOf(income.subtract(expend).toString()));
                merchantFund.setTotalExpend(Double.valueOf(totalExpend.toString()));
                return merchantFund;
            }).collect(Collectors.toList());
            pageResult.setUrl(Routes.MALL_MERCHANT_FUND_FLOW_PAGE);
            jsonResult.data = pageResult;
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /mall/merchant/total/fund 平台 财务 商家资金 (某个商家收入汇总)
     * @apiGroup MALL_MERCHANT_FUND
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {Long} merchantId 商家ID
     *
     * @apiSuccess {BigDecimal} totalIncome 账户累计收入
     * @apiSuccess {BigDecimal} totalExpend 账户累计支出
     * @apiSuccess {String} merchantName 商家名称
     * @apiSuccess {Long} merchantId 商家ID
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     * "code": "1",
     * "desc": "成功"
     * "data":{
     *      "totalIncome": 3242,
     *      "merchantName": "dad",
     *      "totalExpend": 3242
     *      "merchantId": 12
     *  }
     * }
     */
    @RequestMapping(value = Routes.MALL_MERCHANT_TOTAL_FUND, method = RequestMethod.GET)
    public JsonResult merchantTotalFund(HttpServletRequest request, MerchantFundDto dto) {
        UserInfoDto userDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (dto.getMerchantId() == null) {
                jsonResult.remind("商家ID 不能为空",log);
                return;
            }
            MerchantFund merchantFund = merchantFundRepository.findByMallIdAndMerchantId(userDto.mall.getId(), dto.getMerchantId());
            if (merchantFund == null) {
                jsonResult.remind(MerchantFund.REMIND_RECORD_IS_NOT_EXIST,log);;
                return;
            }
            RBeanUtils.copyProperties(merchantFund, dto);
            Merchant merchant = merchantRepository.findByIdAndMallId(merchantFund.getMerchantId(), merchantFund.getMallId());
            dto.setMerchantName(merchant.getName());
            List<MerchantFundFlow> merchantFundFlowList = merchantFundFlowRepository.findByMerchantIdAndMallId(merchantFund.getMerchantId(), merchantFund.getMallId());
            BigDecimal expend = BigDecimal.ZERO;
            BigDecimal income = BigDecimal.ZERO;
            BigDecimal totalExpend = BigDecimal.ZERO;
            for (MerchantFundFlow merchantFundFlow : merchantFundFlowList) {

                if (FundTransactionFlow.INCOME == merchantFundFlow.getTransactionFlow()) { //若有充值,要加条件判断
                    income = income.add(merchantFundFlow.getOperationAmount());
                }
                if (FundTransactionFlow.EXPEND == merchantFundFlow.getTransactionFlow()) { //若有提现,到时要提现 增值服务之类,要加条件判断
                    if (MerchantFundFlowTransactionType.A_APPLY_WITHDRAW_EXPEND == merchantFundFlow.getTransactionType()) {
                        totalExpend = totalExpend.add(merchantFundFlow.getOperationAmount());
                    }else{
                        expend = expend.add(merchantFundFlow.getOperationAmount());
                    }
                }
            }
            dto.setTotalIncome(Double.valueOf(income.subtract(expend).toString()));
            dto.setTotalExpend(Double.valueOf(totalExpend.toString()));
            jsonResult.data = dto;
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /mall/merchant/fund/flow/info 平台 财务 商家资金 明细
     * @apiGroup MALL_MERCHANT_FUND
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {Long} merchantId <code>必传参数</code> 商家ID
     * @apiParam {String} merchantOrderNum 商家订单号
     * @apiParam {String} beginDate 开始日期
     * @apiParam {String} endDate 结束日期
     * @apiParam {String=ALL("全部"), A_ORDER_SETTLEMENT_INCOME("自营收入"),A_ORDER_RESELL_FEE_INCOME("分销收入”), A_RECHARGE_INCOME("普通充值"), A_RECHARGE_PRESENTED("充值赠送”), A_APPLY_WITHDRAW_EXPEND(“提现记录"), A_MERCHANT_SERVICE_FEE_EXPEND(“服务扣费”),MERCHANT_SERVICE_FEE_INCOME("商户基础服务费"),A_ORDER_SERVICE_FEE_ARREARS_EXPEND("服务费支出")} transactionType <code>必传参数</code> 收支类型
     * @apiParam {String=ALL("全部"), ONLINE("线上支付"), OUTLINE("线下支付"), RECHARGE_MALL("平台支付")} payType  <code>必传参数</code> 支付类型

     * @apiSuccess {String} merchantOrderNum 商家订单号
     * @apiSuccess {BigDecimal} operationAmount 收入\支出
     * @apiSuccess {BigDecimal} totalAmount 账户总金额
     * @apiSuccess {Date} lastUpdated 时间
     * @apiSuccess {String=A_ORDER_SETTLEMENT_INCOME("自营收入"),A_ORDER_RESELL_FEE_INCOME("分销收入”), A_RECHARGE_INCOME("普通充值"), A_RECHARGE_PRESENTED("充值赠送”), A_APPLY_WITHDRAW_EXPEND(“提现记录"), A_MERCHANT_SERVICE_FEE_EXPEND(“服务扣费”),A_ORDER_SERVICE_FEE_ARREARS_EXPEND("服务费支出")} transactionType 收支类型
     * @apiSuccess {String=ONLINE("线上支付"), OUTLINE("线下支付"), RECHARGE_MALL("平台支付")} payType 支付类型
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     * "code": "1",
     * "desc": "成功"
     * "data":{
     *      "merchantOrderNum": "3534534534",
     *      "operationAmount": 3242,
     *      "totalAmount": 3242,
     *      "lastUpdated": "2016-08-11 16:27:32",
     *      "transactionType": "A_ORDER_SETTLEMENT_INCOME"
     *  }
     * }
     */
    @RequestMapping(value = Routes.MALL_MERCHANT_FUND_FLOW_INFO, method = RequestMethod.GET)
    public JsonResult mallMerchantFundFlowInfo(HttpServletRequest request, MerchantFundFlowDto dto){
        UserInfoDto userDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (dto.getMerchantId() == null) {
                jsonResult.remind("商家ID 不能为空",log);
                return;
            }

            if (StringUtils.isBlank(dto.getTransactionType()) || !EnumUtils.isValidEnum(MerchantFundFlowTransactionType.class, dto.getTransactionType())) {
                jsonResult.remind("收支类型只允许 ALL(\"全部\") A_ORDER_SETTLEMENT_INCOME(\"自营收入\"), A_ORDER_RESELL_FEE_INCOME(\"分销收入\")",log);
                return;
            }

            if (StringUtils.isBlank(dto.getPayType()) || !EnumUtils.isValidEnum(MerchantPayType.class, dto.getPayType())) {
                jsonResult.remind("支付类型只允许 ALL(\"全部\"), ONLINE(\"线上支付\"), OUTLINE(\"线下支付\"), RECHARGE_MALL(\"平台支付\")",log);
                return;
            }
            PageResult<MerchantFundFlowDto> pageResult = merchantFundFlowRepository.findMerchantFundFlowPage(FundTransactionFlow.ALL.toString(), dto.getTransactionType(), dto.getMerchantOrderNum(), dto.getPayType(),dto.getBeginDate(), dto.getEndDate(), dto.getMerchantId(), userDto.mall.getId(), this.getPage(dto.getPageNo(), dto.getPageSize()));
            pageResult.data.stream().map(merchantFundFlowDto ->{
                Long id = merchantFundFlowDto.getId();
                if (MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME == MerchantFundFlowTransactionType.valueOf(merchantFundFlowDto.getTransactionType())) {
                    id = merchantFundFlowDto.getParentId();
                }
                if (MerchantFundFlowTransactionType.A_ORDER_SETTLEMENT_INCOME == MerchantFundFlowTransactionType.valueOf(merchantFundFlowDto.getTransactionType())) {
                    List<MerchantFundFlow> merchantFundFlowList = merchantFundFlowRepository.findByParentIdAndMerchantIdAndMallIdOrderByDateCreatedDesc(id, merchantFundFlowDto.getMerchantId(), merchantFundFlowDto.getMallId());
                    merchantFundFlowList.stream().filter(fundFlow -> MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME != fundFlow.getTransactionType() && MerchantFundFlowTransactionType.A_ORDER_SETTLEMENT_INCOME != fundFlow.getTransactionType()).forEach(fundFlow -> {
                        if (MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_EXPEND == fundFlow.getTransactionType() || MerchantFundFlowTransactionType.A_ORDER_SERVICE_FEE_EXPEND == fundFlow.getTransactionType() || MerchantFundFlowTransactionType.A_ORDER_SHARE_FEE_EXPEND == fundFlow.getTransactionType()) {
                            if (new BigDecimal(merchantFundFlowDto.getTotalAmount()).compareTo(fundFlow.getTotalAmount()) > 0) {
                                merchantFundFlowDto.setTotalAmount(Double.valueOf(fundFlow.getTotalAmount().toString()));
                            }
                        }
                        merchantFundFlowDto.setOperationAmount(merchantFundFlowDto.getOperationAmount().subtract(fundFlow.getOperationAmount()));
                    });
                }
                return merchantFundFlowDto;
            }).collect(Collectors.toList());
            pageResult.setUrl(Routes.MALL_MERCHANT_FUND_FLOW_INFO);
            jsonResult.data = pageResult;
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /mall/merchant/fund/flow/export 平台 财务 商家资金 报表excel导出
     * @apiGroup MALL_MERCHANT_FUND
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {String} merchantName 商家名称
     * @apiParam {String} merchantAccount 商家帐号
     *
     * @apiSuccess {String} certificateUrl 提现帐号信息 (提现成功,显示该字段值)
     * @apiSuccess {String} remark 备注 (提现失败,显示该字段值)
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     *  }
     */
    @RequestMapping(value = Routes.MALL_MERCHANT_FUND_FLOW_EXPORT, method = RequestMethod.GET)
    public JsonResult mallMerchantFundFlowExport (HttpServletRequest request, HttpServletResponse response, MerchantFundDto dto) {
        UserInfoDto userDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            List<MerchantFundDto> merchantFundDtoList = merchantFundRepository.findMallMerchantFundFlowExport(userDto.mall.getId(), dto.getMerchantName(), dto.getMerchantAccount());
            merchantFundDtoList.stream().map(merchantFund ->{
                //累计收入   充值算收入?
                List<MerchantFundFlow> merchantFundFlowList = merchantFundFlowRepository.findByMerchantIdAndMallId(merchantFund.getMerchantId(), merchantFund.getMallId());
                BigDecimal expend = BigDecimal.ZERO;
                BigDecimal totalExpend = BigDecimal.ZERO;
                BigDecimal income = BigDecimal.ZERO;
                for (MerchantFundFlow merchantFundFlow : merchantFundFlowList) {
                    if (FundTransactionFlow.INCOME == merchantFundFlow.getTransactionFlow()) { //若有充值,要加条件判断
                        income = income.add(merchantFundFlow.getOperationAmount());
                    }
                    if (FundTransactionFlow.EXPEND == merchantFundFlow.getTransactionFlow()) { //若有提现,到时要提现 增值服务之类,要加条件判断
                        if (MerchantFundFlowTransactionType.A_APPLY_WITHDRAW_EXPEND != merchantFundFlow.getTransactionType()) {
                            expend = expend.add(merchantFundFlow.getOperationAmount());
                        }else{
                            totalExpend = totalExpend.add(merchantFundFlow.getOperationAmount());
                        }
                    }

                }
                merchantFund.setTotalIncome(Double.valueOf(income.subtract(expend).toString()));
                merchantFund.setTotalExpend(Double.valueOf(totalExpend.toString()));
                return merchantFund;
            }).collect(Collectors.toList());
            String[] title = {"商家ID", "商户名称", "账户累计收入", "账户累计支出", "账户总余额", "可用余额", "锁定余额"};
            String[] columnName = {"merchantId", "merchantName", "totalIncome", "totalExpend", "totalAmount", "availableAmount", "frozen"};
            //excel报表导出
            ExcelExportUtils.excelExport(title, columnName, merchantFundDtoList, response);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /mall/merchant/fund/flow/info/export 平台 财务 商家资金 明细报表excel导出
     * @apiGroup MALL_MERCHANT_FUND
     * @apiVersion 1.0.0
     * @apiHeader {String} userToken 用户token
     * @apiHeader {String} domain 请求域名
     *
     * @apiParam {Long} merchantId <code>必传参数</code> 商家ID
     * @apiSuccess {String} merchantOrderNum 商家订单号
     * @apiSuccess {String} beginDate 开始日期
     * @apiSuccess {String} endDate 结束日期
     * @apiParam {String=ALL("全部"), A_ORDER_SETTLEMENT_INCOME("自营收入"), A_ORDER_RESELL_FEE_INCOME("分销收入")} transactionType <code>必传参数</code> 收支类型
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     *  }
     */
    @RequestMapping(value = Routes.MALL_MERCHANT_FUND_FLOW_INFO_EXPORT, method = RequestMethod.GET)
    public JsonResult mallMerchantFundFlowInfoExport (HttpServletRequest request, HttpServletResponse response, MerchantFundFlowDto dto) {
        UserInfoDto userDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (dto.getMerchantId() == null) {
                jsonResult.remind("商家ID 不能为空",log);
                return;
            }

            if (StringUtils.isBlank(dto.getTransactionType()) || !EnumUtils.isValidEnum(MerchantFundFlowTransactionType.class, dto.getTransactionType())) {
                jsonResult.remind("收支类型只允许 ALL(\"全部\") A_ORDER_SETTLEMENT_INCOME(\"自营收入\"), A_ORDER_RESELL_FEE_INCOME(\"分销收入\")",log);
                return;
            }
            List<MerchantFundFlowDto> merchantFundFlowDtoList = merchantFundFlowRepository.findMallMerchantFundFlowInfoExport(FundTransactionFlow.ALL.toString(), dto.getTransactionType(), dto.getMerchantOrderNum(), dto.getBeginDate(), dto.getEndDate(), dto.getMerchantId(), userDto.mall.getId());
            merchantFundFlowDtoList.stream().map(merchantFundFlowDto ->{
                Long id = merchantFundFlowDto.getId();
                if (MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME == MerchantFundFlowTransactionType.valueOf(merchantFundFlowDto.getTransactionType())) {
                    id = merchantFundFlowDto.getParentId();
                }
                if (MerchantFundFlowTransactionType.A_ORDER_SETTLEMENT_INCOME == MerchantFundFlowTransactionType.valueOf(merchantFundFlowDto.getTransactionType())) {
                    List<MerchantFundFlow> merchantFundFlowList = merchantFundFlowRepository.findByParentIdAndMerchantIdAndMallIdOrderByDateCreatedDesc(id, merchantFundFlowDto.getMerchantId(), merchantFundFlowDto.getMallId());
                    merchantFundFlowList.stream().filter(fundFlow -> MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME != fundFlow.getTransactionType() && MerchantFundFlowTransactionType.A_ORDER_SETTLEMENT_INCOME != fundFlow.getTransactionType()).forEach(fundFlow -> {
                        if (MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_EXPEND == fundFlow.getTransactionType() || MerchantFundFlowTransactionType.A_ORDER_SERVICE_FEE_EXPEND == fundFlow.getTransactionType() || MerchantFundFlowTransactionType.A_ORDER_SHARE_FEE_EXPEND == fundFlow.getTransactionType()) {
                            if (new BigDecimal(merchantFundFlowDto.getTotalAmount()).compareTo(fundFlow.getTotalAmount()) > 0) {
                                log.info("======================>");
                                merchantFundFlowDto.setTotalAmount(Double.valueOf(fundFlow.getTotalAmount().toString()));
                            }
                        }
                        merchantFundFlowDto.setOperationAmount(merchantFundFlowDto.getOperationAmount().subtract(fundFlow.getOperationAmount()));
                    });
                }
                if (FundTransactionFlow.EXPEND == FundTransactionFlow.valueOf(merchantFundFlowDto.getTransactionFlow())) {
                    merchantFundFlowDto.setActualAmount("-" + merchantFundFlowDto.getOperationAmount());
                }
                if (FundTransactionFlow.INCOME == FundTransactionFlow.valueOf(merchantFundFlowDto.getTransactionFlow())) {
                    merchantFundFlowDto.setActualAmount("+" + merchantFundFlowDto.getOperationAmount());
                }
                merchantFundFlowDto.setTransactionType(MerchantFundFlowTransactionType.valueOf(merchantFundFlowDto.getTransactionType()).getValue());
                return merchantFundFlowDto;
            }).collect(Collectors.toList());
            String[] title = {"时间", "收支类型", "商家订单号", "收支金额", "账户余额"};
            String[] columnName = {"createDate", "transactionType", "merchantOrderNum", "actualAmount", "totalAmount"};
            //excel报表导出
            ExcelExportUtils.excelExport(title, columnName, merchantFundFlowDtoList, response);
        };
        return doing.go(request, log);
    }
}
